/*

	TP2 - Algoritmos y Programación 2 - Cátedra Wachenchauzer - FIUBA

	Segundo Cuatrimestre 2013

	Alumno: Maximiliano Alexis Montiel
	Padrón: 93157

	Sistema Messi +10. 
	
	Implementacion del sistema.

*/
#include "system.h"

#include "hash.h"

#include <string.h>

static hash_t *sistema = NULL;

error_code System_Init(void)
{
	if (sistema)
		return SISTEMA_HAY;
	
	return (sistema = hash_crear(NULL))?EXITO:ERROR_MEMORIA;
}

error_code System_Close(void)
{
	if (!sistema)
		return SISTEMA_NO_HAY;

	hash_destruir(sistema);
	return EXITO;
}

error_code System_Install(const char *nombre, comando_t funcion)
{
	if (!sistema)
		return SISTEMA_HAY;

	if (!nombre || !funcion)
		return ERROR_PARAMETRO;

	return hash_guardar(sistema,nombre,(void *)(size_t)funcion)?EXITO:ERROR_MEMORIA;
}

comando_t asociar_comando(const char *nombre_comando, error_code *error)
{
	if (!sistema)
		{
			*error = SISTEMA_NO_HAY;
			return NULL;
		}

	if (!nombre_comando || !error)
		{
			*error = ERROR_PARAMETRO;
			return NULL;
		}

	comando_t comando = (comando_t)(size_t)hash_obtener(sistema, nombre_comando);
	*error = comando?EXITO:COMANDO_INVALIDO;
	return comando;
}

error_code System_execute(void *entorno, lista_t *lista)
{
	if (!sistema)
		return SISTEMA_NO_HAY;
	
	if (!lista || !entorno)
		return ERROR_PARAMETRO;

	// Obtenemos el primer elemento, el cual es el nombre del comando.
	char *nombre_comando = lista_borrar_primero(lista);

	// Si es inválido, NO HACEMOS NADA.
	if (!nombre_comando)
		return ERROR_PARAMETRO;

	// Obtenemos el comando asociado (el apuntador a función).
	error_code error;
	comando_t orden = asociar_comando(nombre_comando, &error);

	if (error == EXITO)
		{
			// Si es válido, hacemos la llamada.
			if (orden)
				orden(entorno,lista);
			else
				error = COMANDO_INVALIDO;
		}

	// Regresamos el nombre del comando a la lista.
	if (!lista_insertar_primero(lista,nombre_comando))
		free(nombre_comando);

	return error;
}
